﻿using Microsoft.Extensions.Hosting;
using System.Net.Sockets;

namespace 天离安全_天擎.Tl_SerVices
{
    /// <summary>
    /// 端口扫描服务
    /// </summary>
    public class PortScan_SerVices
    {
        private static int MaxDegreeOfParallelism = Tl_Api.PortScan_Api.Max; // 最大并发线程数
        private static int StrPort = Tl_Api.PortScan_Api.Str_Port; // 开始端口
        private static int EndPort = Tl_Api.PortScan_Api.End_Por; // 结束端口
        private static int[] Port = Tl_Api.PortScan_Api.Port; // 默认端口
        private static string Ip = Tl_Api.PortScan_Api.Ip; // 扫描IP地址
        private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(MaxDegreeOfParallelism);
        private static List<int> openPorts = new List<int>(); // 存放开放端口
        /// <summary>
        /// 全端口扫描服务
        /// </summary>
        /// <returns></returns>
        public static async Task PortScan_All()
        {
            var tasks = new List<Task>();

            for (int port = StrPort; port <= EndPort; port++)
            {
                tasks.Add(ScanPortAsync(port));
            }

            // 等待所有任务完成
            await Task.WhenAll(tasks);

            foreach (var openPort in openPorts)
            {
                string s1 = openPort.ToString();
                // 能访问的端口进行动态传出
                Tl_Api.PortScan_Api.Scan_Info.Append(openPort + "\r\n");
            }
        }
        /// <summary>
        /// 默认端口扫描
        /// </summary>
        /// <returns></returns>
        public static async Task PortScan_Default()
        {
            var tasks = new List<Task>();

            // 遍历 Port 数组
            foreach (var port in Port)
            {
                tasks.Add(ScanPortAsync(port, openPorts));
            }

            // 等待所有任务完成
            await Task.WhenAll(tasks);

            foreach (var openPort in openPorts)
            {
                string s1 = openPort.ToString();
                // 能访问的端口进行动态传出
                Tl_Api.PortScan_Api.Scan_Info.Append(openPort + "\r\n");
            }
        }
        /// <summary>
        /// 异步扫描特定端口
        /// </summary>
        /// <param name="port">要扫描的端口号</param>
        private static async Task ScanPortAsync(int port)
        {
            await semaphore.WaitAsync(); // 请求一个许可
            try
            {
                using (var client = new TcpClient())
                {
                    var connectTask = client.ConnectAsync(Ip, port);
                    var completedTask = await Task.WhenAny(connectTask, Task.Delay(500));

                    if (completedTask == connectTask)
                    {
                        // 连接成功
                        lock (openPorts) // 添加锁以防止并发修改
                        {
                            openPorts.Add(port);
                        }
                    }
                }
            }
            catch (SocketException)
            {
                // 端口关闭或主机不可达
                Tl_Api.PortScan_Api.Scan_Error.Append("端口或网络访问异常！");
            }
            finally
            {
                semaphore.Release(); // 释放许可
            }
        }
        private static async Task ScanPortAsync(int port, List<int> openPorts)
        {
            using var client = new TcpClient();
            try
            {
                // 尝试连接指定的 IP 和端口
                await client.ConnectAsync(Ip, port);
                Console.WriteLine($"Port {port} is open on {Ip}.");
                openPorts.Add(port); // 如果连接成功，添加到开放端口列表
            }
            catch (SocketException)
            {
                Console.WriteLine($"Port {port} is closed on {Ip}.");
            }
        }
    }
}
